#include "qsingleapplication.h"
#include <QLocalSocket>
#include <QDebug>

QSingleApplication::QSingleApplication(int &argc, char **argv, const QString uniqueKey)
    : QApplication(argc, argv)
    , uniqueKey(uniqueKey)
    , localServer(nullptr)
{
#ifndef Q_OS_WIN32
//#ifdef QT_DEBUG
    QSharedMemory nix_fix_shared_memory(uniqueKey);
    if (nix_fix_shared_memory.attach())
    {
        nix_fix_shared_memory.detach();
    }
//#endif
#endif

    sharedMemory.setKey(uniqueKey);
    if (sharedMemory.attach())
    {
        running = true;
        return;
    }

    running = false;
    if (!sharedMemory.create(1))
    {
        return;
    }

    QLocalServer::removeServer(uniqueKey);
    localServer = new QLocalServer(this);
    connect(localServer, SIGNAL(newConnection()), this, SLOT(receiveMessage()));
    bool result = localServer->listen(uniqueKey);
    qDebug() << "listen result: " << result;
}

QSingleApplication::~QSingleApplication()
{
    if (localServer)
    {
        localServer->deleteLater();
        localServer = nullptr;
    }
}

bool QSingleApplication::isRunning()
{
    return running;
}

bool QSingleApplication::sendMessage(const QString &message)
{
    if (!running)
    {
        return false;
    }
    QLocalSocket localSocket(this);
    localSocket.connectToServer(uniqueKey, QIODevice::WriteOnly);
    if (!localSocket.waitForConnected(timeout))
    {
        qDebug() << "waitForConnected: " << localSocket.errorString();
        return false;
    }

    localSocket.write(message.toUtf8());
    if (!localSocket.waitForBytesWritten(timeout))
    {
        qDebug() << "waitForBytesWritten: " << localSocket.errorString();
        return false;
    }
    localSocket.disconnectFromServer();
    return true;
}

void QSingleApplication::closeLocalServer()
{
    running = false;
    sharedMemory.detach();
    QLocalServer::removeServer(uniqueKey);

    if (localServer)
    {
        localServer->deleteLater();
        localServer = nullptr;
    }
}

void QSingleApplication::receiveMessage()
{
    QLocalSocket *localSocket = localServer->nextPendingConnection();
    if (!localSocket->waitForReadyRead(timeout))
    {
        qDebug() << "waitForReadyRead: " << localSocket->errorString();
        return;
    }
    QByteArray byteArray = localSocket->readAll();
    QString message = QString::fromUtf8(byteArray.constData());
    emit messageAvailable(message);
    localSocket->disconnectFromServer();
}
